<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>The source code</title>
  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  <style type="text/css">
    .highlight { display: block; background-color: #ddd; }
  </style>
  <script type="text/javascript">
    function highlight() {
      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
    }
  </script>
</head>
<body onload="prettyPrint(); highlight();">
  <pre class="prettyprint lang-js"><span id='Ext-tree-DefaultSelectionModel'>/**
</span> * @class Ext.tree.DefaultSelectionModel
 * @extends Ext.util.Observable
 * The default single selection for a TreePanel.
 */
Ext.tree.DefaultSelectionModel = Ext.extend(Ext.util.Observable, {
    
<span id='Ext-tree-DefaultSelectionModel-method-constructor'>    constructor : function(config){
</span>        this.selNode = null;
   
        this.addEvents(
<span id='Ext-tree-DefaultSelectionModel-event-selectionchange'>            /**
</span>             * @event selectionchange
             * Fires when the selected node changes
             * @param {DefaultSelectionModel} this
             * @param {TreeNode} node the new selection
             */
            'selectionchange',

<span id='Ext-tree-DefaultSelectionModel-event-beforeselect'>            /**
</span>             * @event beforeselect
             * Fires before the selected node changes, return false to cancel the change
             * @param {DefaultSelectionModel} this
             * @param {TreeNode} newNode the new selection
             * @param {TreeNode} oldNode the old selection
             */
            'beforeselect'
        );

        Ext.apply(this, config);
        Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);    
    },
    
<span id='Ext-tree-DefaultSelectionModel-method-init'>    init : function(tree){
</span>        this.tree = tree;
        tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
        tree.on('click', this.onNodeClick, this);
    },
    
<span id='Ext-tree-DefaultSelectionModel-method-onNodeClick'>    onNodeClick : function(node, e){
</span>        this.select(node);
    },
    
<span id='Ext-tree-DefaultSelectionModel-method-select'>    /**
</span>     * Select a node.
     * @param {TreeNode} node The node to select
     * @return {TreeNode} The selected node
     */
    select : function(node, /* private*/ selectNextNode){
        // If node is hidden, select the next node in whatever direction was being moved in.
        if (!Ext.fly(node.ui.wrap).isVisible() &amp;&amp; selectNextNode) {
            return selectNextNode.call(this, node);
        }
        var last = this.selNode;
        if(node == last){
            node.ui.onSelectedChange(true);
        }else if(this.fireEvent('beforeselect', this, node, last) !== false){
            if(last &amp;&amp; last.ui){
                last.ui.onSelectedChange(false);
            }
            this.selNode = node;
            node.ui.onSelectedChange(true);
            this.fireEvent('selectionchange', this, node, last);
        }
        return node;
    },
    
<span id='Ext-tree-DefaultSelectionModel-method-unselect'>    /**
</span>     * Deselect a node.
     * @param {TreeNode} node The node to unselect
     * @param {Boolean} silent True to stop the selectionchange event from firing.
     */
    unselect : function(node, silent){
        if(this.selNode == node){
            this.clearSelections(silent);
        }    
    },
    
<span id='Ext-tree-DefaultSelectionModel-method-clearSelections'>    /**
</span>     * Clear all selections
     * @param {Boolean} silent True to stop the selectionchange event from firing.
     */
    clearSelections : function(silent){
        var n = this.selNode;
        if(n){
            n.ui.onSelectedChange(false);
            this.selNode = null;
            if(silent !== true){
                this.fireEvent('selectionchange', this, null);
            }
        }
        return n;
    },
    
<span id='Ext-tree-DefaultSelectionModel-method-getSelectedNode'>    /**
</span>     * Get the selected node
     * @return {TreeNode} The selected node
     */
    getSelectedNode : function(){
        return this.selNode;    
    },
    
<span id='Ext-tree-DefaultSelectionModel-method-isSelected'>    /**
</span>     * Returns true if the node is selected
     * @param {TreeNode} node The node to check
     * @return {Boolean}
     */
    isSelected : function(node){
        return this.selNode == node;  
    },

<span id='Ext-tree-DefaultSelectionModel-method-selectPrevious'>    /**
</span>     * Selects the node above the selected node in the tree, intelligently walking the nodes
     * @return TreeNode The new selection
     */
    selectPrevious : function(/* private */ s){
        if(!(s = s || this.selNode || this.lastSelNode)){
            return null;
        }
        // Here we pass in the current function to select to indicate the direction we're moving
        var ps = s.previousSibling;
        if(ps){
            if(!ps.isExpanded() || ps.childNodes.length &lt; 1){
                return this.select(ps, this.selectPrevious);
            } else{
                var lc = ps.lastChild;
                while(lc &amp;&amp; lc.isExpanded() &amp;&amp; Ext.fly(lc.ui.wrap).isVisible() &amp;&amp; lc.childNodes.length &gt; 0){
                    lc = lc.lastChild;
                }
                return this.select(lc, this.selectPrevious);
            }
        } else if(s.parentNode &amp;&amp; (this.tree.rootVisible || !s.parentNode.isRoot)){
            return this.select(s.parentNode, this.selectPrevious);
        }
        return null;
    },

<span id='Ext-tree-DefaultSelectionModel-method-selectNext'>    /**
</span>     * Selects the node above the selected node in the tree, intelligently walking the nodes
     * @return TreeNode The new selection
     */
    selectNext : function(/* private */ s){
        if(!(s = s || this.selNode || this.lastSelNode)){
            return null;
        }
        // Here we pass in the current function to select to indicate the direction we're moving
        if(s.firstChild &amp;&amp; s.isExpanded() &amp;&amp; Ext.fly(s.ui.wrap).isVisible()){
             return this.select(s.firstChild, this.selectNext);
         }else if(s.nextSibling){
             return this.select(s.nextSibling, this.selectNext);
         }else if(s.parentNode){
            var newS = null;
            s.parentNode.bubble(function(){
                if(this.nextSibling){
                    newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
                    return false;
                }
            });
            return newS;
         }
        return null;
    },

<span id='Ext-tree-DefaultSelectionModel-method-onKeyDown'>    onKeyDown : function(e){
</span>        var s = this.selNode || this.lastSelNode;
        // undesirable, but required
        var sm = this;
        if(!s){
            return;
        }
        var k = e.getKey();
        switch(k){
             case e.DOWN:
                 e.stopEvent();
                 this.selectNext();
             break;
             case e.UP:
                 e.stopEvent();
                 this.selectPrevious();
             break;
             case e.RIGHT:
                 e.preventDefault();
                 if(s.hasChildNodes()){
                     if(!s.isExpanded()){
                         s.expand();
                     }else if(s.firstChild){
                         this.select(s.firstChild, e);
                     }
                 }
             break;
             case e.LEFT:
                 e.preventDefault();
                 if(s.hasChildNodes() &amp;&amp; s.isExpanded()){
                     s.collapse();
                 }else if(s.parentNode &amp;&amp; (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
                     this.select(s.parentNode, e);
                 }
             break;
        };
    }
});

<span id='Ext-tree-MultiSelectionModel'>/**
</span> * @class Ext.tree.MultiSelectionModel
 * @extends Ext.util.Observable
 * Multi selection for a TreePanel.
 */
Ext.tree.MultiSelectionModel = Ext.extend(Ext.util.Observable, {
    
<span id='Ext-tree-MultiSelectionModel-method-constructor'>    constructor : function(config){
</span>        this.selNodes = [];
        this.selMap = {};
        this.addEvents(
<span id='Ext-tree-MultiSelectionModel-event-selectionchange'>            /**
</span>             * @event selectionchange
             * Fires when the selected nodes change
             * @param {MultiSelectionModel} this
             * @param {Array} nodes Array of the selected nodes
             */
            'selectionchange'
        );
        Ext.apply(this, config);
        Ext.tree.MultiSelectionModel.superclass.constructor.call(this);    
    },
    
<span id='Ext-tree-MultiSelectionModel-method-init'>    init : function(tree){
</span>        this.tree = tree;
        tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
        tree.on('click', this.onNodeClick, this);
    },
    
<span id='Ext-tree-MultiSelectionModel-method-onNodeClick'>    onNodeClick : function(node, e){
</span>        if(e.ctrlKey &amp;&amp; this.isSelected(node)){
            this.unselect(node);
        }else{
            this.select(node, e, e.ctrlKey);
        }
    },
    
<span id='Ext-tree-MultiSelectionModel-method-select'>    /**
</span>     * Select a node.
     * @param {TreeNode} node The node to select
     * @param {EventObject} e (optional) An event associated with the selection
     * @param {Boolean} keepExisting (optional) True to retain existing selections
     * @return {TreeNode} The selected node
     */
    select : function(node, e, keepExisting){
        if(keepExisting !== true){
            this.clearSelections(true);
        }
        if(this.isSelected(node)){
            this.lastSelNode = node;
            return node;
        }
        this.selNodes.push(node);
        this.selMap[node.id] = node;
        this.lastSelNode = node;
        node.ui.onSelectedChange(true);
        this.fireEvent('selectionchange', this, this.selNodes);
        return node;
    },
    
<span id='Ext-tree-MultiSelectionModel-method-unselect'>    /**
</span>     * Deselect a node.
     * @param {TreeNode} node The node to unselect
     */
    unselect : function(node){
        if(this.selMap[node.id]){
            node.ui.onSelectedChange(false);
            var sn = this.selNodes;
            var index = sn.indexOf(node);
            if(index != -1){
                this.selNodes.splice(index, 1);
            }
            delete this.selMap[node.id];
            this.fireEvent('selectionchange', this, this.selNodes);
        }
    },
    
<span id='Ext-tree-MultiSelectionModel-method-clearSelections'>    /**
</span>     * Clear all selections
     */
    clearSelections : function(suppressEvent){
        var sn = this.selNodes;
        if(sn.length &gt; 0){
            for(var i = 0, len = sn.length; i &lt; len; i++){
                sn[i].ui.onSelectedChange(false);
            }
            this.selNodes = [];
            this.selMap = {};
            if(suppressEvent !== true){
                this.fireEvent('selectionchange', this, this.selNodes);
            }
        }
    },
    
<span id='Ext-tree-MultiSelectionModel-method-isSelected'>    /**
</span>     * Returns true if the node is selected
     * @param {TreeNode} node The node to check
     * @return {Boolean}
     */
    isSelected : function(node){
        return this.selMap[node.id] ? true : false;  
    },
    
<span id='Ext-tree-MultiSelectionModel-method-getSelectedNodes'>    /**
</span>     * Returns an array of the selected nodes
     * @return {Array}
     */
    getSelectedNodes : function(){
        return this.selNodes.concat([]);
    },

<span id='Ext-tree-MultiSelectionModel-property-onKeyDown'>    onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
</span>
<span id='Ext-tree-MultiSelectionModel-property-selectNext'>    selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
</span>
<span id='Ext-tree-MultiSelectionModel-property-selectPrevious'>    selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
</span>});</pre>
</body>
</html>
